MexicoMapsLink="https://github.com/AyeliAlp/ejercicicios_sem11/raw/main/maps/mexicoMaps_6366.gpkg"

from  fiona import listlayers


#layers in maps
listlayers(MexicoMapsLink)
['country',
'cities',
'rivers',
'border',
'airports',
'states',
'municipalities']
#Realizamos la lectura de los datos:

import os
os.environ['USE_PYGEOS'] = '0'

import geopandas as gpd

states=gpd.read_file(MexicoMapsLink,layer='states')
municipalities=gpd.read_file(MexicoMapsLink,layer='municipalities')
airports=gpd.read_file(MexicoMapsLink,layer='airports')
rivers=gpd.read_file(MexicoMapsLink,layer='rivers')
border=gpd.read_file(MexicoMapsLink,layer='border')
#Primero descargamos informacion importante sobre los principales puertos y terminales a nivel mundial
#y los leemos
import pandas as pd 
infoseaports=pd.read_csv(os.path.join("data","UpdatedPub150.csv"))

#columns available (so many)
infoseaports.columns.to_list()
['World Port Index Number',
'Region Name',
'Main Port Name',
'Alternate Port Name',
'UN/LOCODE',
'Country Code',
'World Water Body',
'IHO S-130 Sea Area',
'Sailing Direction or Publication',
'Publication Link',
'Standard Nautical Chart',
'IHO S-57 Electronic Navigational Chart',
'IHO S-101 Electronic Navigational Chart',
'Digital Nautical Chart',
'Tidal Range (m)',
'Entrance Width (m)',
'Channel Depth (m)',
'Anchorage Depth (m)',
'Cargo Pier Depth (m)',
'Oil Terminal Depth (m)',
'Liquified Natural Gas Terminal Depth (m)',
'Maximum Vessel Length (m)',
'Maximum Vessel Beam (m)',
'Maximum Vessel Draft (m)',
'Offshore Maximum Vessel Length (m)',
'Offshore Maximum Vessel Beam (m)',
'Offshore Maximum Vessel Draft (m)',
'Harbor Size',
'Harbor Type',
'Harbor Use',
'Shelter Afforded',
'Entrance Restriction - Tide',
'Entrance Restriction - Heavy Swell',
'Entrance Restriction - Ice',
'Entrance Restriction - Other',
'Overhead Limits',
'Underkeel Clearance Management System',
'Good Holding Ground',
'Turning Area',
'Port Security',
'Estimated Time of Arrival Message',
'Quarantine - Pratique',
'Quarantine - Sanitation',
'Quarantine - Other',
'Traffic Separation Scheme',
'Vessel Traffic Service',
'First Port of Entry',
'US Representative',
'Pilotage - Compulsory',
'Pilotage - Available',
'Pilotage - Local Assistance',
'Pilotage - Advisable',
'Tugs - Salvage',
'Tugs - Assistance',
'Communications - Telephone',
'Communications - Telefax',
'Communications - Radio',
'Communications - Radiotelephone',
'Communications - Airport',
'Communications - Rail',
'Search and Rescue',
'NAVAREA',
'Facilities - Wharves',
'Facilities - Anchorage',
'Facilities - Dangerous Cargo Anchorage',
'Facilities - Med Mooring',
'Facilities - Beach Mooring',
'Facilities - Ice Mooring',
'Facilities - Ro-Ro',
'Facilities - Solid Bulk',
'Facilities - Liquid Bulk',
'Facilities - Container',
'Facilities - Breakbulk',
'Facilities - Oil Terminal',
'Facilities - LNG Terminal',
'Facilities - Other',
'Medical Facilities',
'Garbage Disposal',
'Chemical Holding Tank Disposal',
'Degaussing',
'Dirty Ballast Disposal',
'Cranes - Fixed',
'Cranes - Mobile',
'Cranes - Floating',
'Cranes - Container',
'Lifts - 100+ Tons',
'Lifts - 50-100 Tons',
'Lifts - 25-49 Tons',
'Lifts - 0-24 Tons',
'Services - Longshoremen',
'Services - Electricity',
'Services - Steam',
'Services - Navigation Equipment',
'Services - Electrical Repair',
'Services - Ice Breaking',
'Services - Diving',
'Supplies - Provisions',
'Supplies - Potable Water',
'Supplies - Fuel Oil',
'Supplies - Diesel Oil',
'Supplies - Aviation Fuel',
'Supplies - Deck',
'Supplies - Engine',
'Repairs',
'Dry Dock',
'Railway',
'Latitude',
'Longitude']
#Primero reenombramos la columna Main Port Name a portName. Luego, obtenemos la información
#general y resumida sobre el DataFrame
infoseaports.rename(columns={'Main Port Name':'portName'},inplace=True)
infoseaports=infoseaports.loc[:,['portName''Country Code','Latitude''Longitude']]
infoseaports.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3774 entries, 0 to 3773
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 portName 3774 non-null object
1 Country Code 3774 non-null object
2 Latitude 3774 non-null float64
3 Longitude 3774 non-null float64
dtypes: float64(2), object(2)
memory usage: 118.1+ KB
#Ahora creamos un nuevo GeoDataFrame llamado "seaports". Además generamos una geometria de puntos a partir de la
#columnas de longitud y latitud. Como podemos notar, no está proyectado. Luego, transformamos los datos de 
#seaports_mex al sistema de referencia de coordenadas proyectado con codigo 6366 
seaports=gpd.GeoDataFrame(data=infoseaports.copy(),
                 geometry=gpd.points_from_xy(infoseaports.Longitude,
                                             infoseaports.Latitude), 
                 crs=4326)# notice it is unprojected

seaports_mex=seaports[seaports['Country Code']=='Mexico'].copy()

seaports_mex.reset_index(drop=Trueinplace=True)

seaports_mex_6366=seaports_mex.to_crs(6366# projected crs
#Creamos un nuevo DataFrame llamado largeAirports seleccionando "airports" donde el valor de la columna
#"kind" es "large_airport". Luego, graficamos los aeropuertos que se representan como triangulos rojos
#y los punto celestes representan a los puertos maritimos de mexico.
# subsetting
largeAirports=airports[airports.kind=='large_airport'
largeAirports.reset_index(drop=Trueinplace=True)

#plotting
base=largeAirports.plot(color='red',marker="^")
seaports_mex_6366.plot(ax=base,alpha=0.5,markersize=3)
<Axes: >
#Exercise 1
#Create two sets of points.

#Compute the distance matrix for both sets.

#Select one row of the distance matrix, and plot the two point with the minimal distance
#Distance
#Between points
#The easiest way to understand distance is to compute how far two coordinates are from each other.

#Visualizamos los puertos maritimos de Mexico:

seaports_mex_6366.head()
#Visualizamos los aeropuertos grandes de Mexico:

largeAirports.head()
#Si ambos GeoDataFrame tienen en el mismo crs proyectado, podemos usar la funcion distancia:

#Calculamos la distancia en kilometros entre la geometria del primer aeropuerto grande que aparece 
#en el DataFrame y la geometria del primer puerto del DataFrame "seaports_mex_6366"
largeAirports.iloc[0].geometry.distance(seaports_mex_6366.iloc[0].geometry)/1000
2602.4465202278006
#Calculamos todas las distancias entre cada geometria de los puertos y todas las geometrias de los
#aeropuertos en km:

#Prueba 1
seaports_mex_6366.geometry.apply\
(lambda g: largeAirports.geometry.distance(g)/1000)
#Aaui tambien calculamos las distancias pero esta vez utilizamos los nombres de los puertos y aeropuertos como indices
#para realizar la comparación, en km.
#Prueba 2
seaports_mex_6366.set_index('portName').geometry.apply\
(lambda g: largeAirports.set_index('name').geometry.distance(g)/1000)
#calculamos las distancias en kilómetros entre cada puerto en seaports_mex_6366 y todos los aeropuertos en largeAirports, utilizando 
#los nombres como índices para realizar la comparación. Luego, ordenamos los resultados por los nombres de los puertos y 
#los nombres de los aeropuertos, tanto en las filas como en las columnas.
#Prueba 3
seaports_mex_6366.set_index('portName').geometry.apply\
(lambda g: largeAirports.set_index('name').geometry.distance(g)/1000).\
sort_index(axis=0).sort_index(axis=1)
#Nos quedamos con la prueba:
#Calculamos una matriz de distancias en kilómetros entre cada puerto en seaports_mex_6366 y todos los aeropuertos en largeAirports, 
#utilizando los nombres como índices para realizar la comparación. La matriz resultante está ordenada por los nombres de los puertos 
#y los nombres de los aeropuertos, tanto en las filas como en las columnas, y le asignamos la variable distanceMatrixKM_sea_air.

distanceMatrixKM_sea_air= seaports_mex_6366.set_index('portName').geometry.apply\
                          (lambda g: largeAirports.set_index('name').geometry.distance(g)/1000).\
                          sort_index(axis=0).sort_index(axis=1)
#Este es un marco de datos (pandas), y las instalaciones son índices de fila y columna. Esto es útil de esta manera:

#calculamos el promedio de las distancias en kilómetros entre cada puerto en seaports_mex_6366 y los aeropuertos en largeAirports, y luego mostr 
#los puertos ordenados en función de sus distancias promedio de menor a mayor
distanceMatrixKM_sea_air.mean(axis=1).sort_values(ascending=True)
#Calcuamos el promedio de las distancias para cada puerto, la distancia minima para cada puerto y 
#la distancia maxima para cada puerto:

SomeStats=pd.DataFrame()
SomeStats['mean']=distanceMatrixKM_sea_air.mean(axis=1)
SomeStats['min']=distanceMatrixKM_sea_air.min(axis=1)
SomeStats['max']=distanceMatrixKM_sea_air.max(axis=1)
SomeStats.head()
#También podemos usar idxmax para obtener las ubicaciones particulares:

#Buscamos el indice del valor maximo en cada fila de la matriz de distancia
#(aeropuerto más lejano a cada puerto marítimo) 
distanceMatrixKM_sea_air.idxmax(axis="columns")
#puerto marítimo más lejano a cada aeropuerto 
distanceMatrixKM_sea_air.idxmax(axis="rows")
#aeropuerto más cercano a cada puerto de mar
distanceMatrixKM_sea_air.idxmin(axis="columns")
#puerto marítimo más cercano a cada aeropuerto
distanceMatrixKM_sea_air.idxmin(axis="rows")
#Ejercicio 2
#Crear un conjunto de puntos y un conjunto de líneas.

#Calcule la matriz de distancias para ambos conjuntos.

#Seleccione una línea de la matriz de distancia y trace el punto más cercano y el más lejano a esa línea.
#Distancia entre línea y punto
#Visualizamos los rios que tenemos:

rivers
#Mantenemos uno:

rivers[rivers.NAME.str.contains('Grande')]
#Puedes ver que la distancia funciona entre estos dos elementos::

rivers[rivers.NAME.str.contains('Grande')].iloc[0].geometry.distance(largeAirports.geometry)
#Basándonos en lo que hicimos anteriormente, calculemos todas las distancias en kilómetros entre cada río en rivers y todos los aeropuertos en largeAirports, 
#utilizando los nombres de los ríos y los aeropuertos como índices.

distanceMatrixKM_riv_air=rivers.set_index('NAME').geometry.apply\
(lambda g: largeAirports.set_index('name').geometry.distance(g)/1000).\
sort_index(axis=0).sort_index(axis=1)
distanceMatrixKM_riv_air
#Aquí, vemos una fila (río), que indica la distancia a cada columna (aeropuerto grande):
distanceMatrixKM_riv_air.loc['Rio Grande, North America'].sort_values()
#Graficamos:

base=rivers[rivers.NAME.str.contains('Grande')].explore()
largeAirports.explore(m=base,color='red',marker_kwds=dict(radius=10))
#Nos centramos en los que pertenecen a un sistema, pero estos datos no presentan informacion sobre 
#quienes pertenecen a un sistema

rivers[~rivers.SYSTEM.isna()]
#Disolvemos los que pertenecen a un sistema en una multilínea:

systems=rivers.dissolve(by='SYSTEM')
systems
#Disolvemos los que pertenecen a un sistema en una multilínea:

# format the GDF:
systems['NAME']=systems.index
systems.reset_index(drop=True,inplace=True)
systems
#Another distance matrix:

distanceMatrixKM_sys_air=systems.set_index('NAME').geometry.apply\
(lambda g: largeAirports.set_index('name').geometry.distance(g)/1000).\
sort_index(axis=0).sort_index(axis=0)

distanceMatrixKM_sys_air
#This time, let me get all the minimum distances:

mins=distanceMatrixKM_sys_air.idxmin(axis="columns")
mins
TypeError: '>=' not supported between instances of 'str' and 'int'
# one of them
mins[1]
NameError: name 'mins' is not defined
base=systems.explore()
# the closest
largeAirports[largeAirports.name.isin(mins)].explore(m=base,color='red',marker_kwds=dict(radius=10))
# the NOT closest
largeAirports[~largeAirports.name.isin(mins)].explore(m=base,color='blue',marker_kwds=dict(radius=5))
ValueError: Location values cannot contain NaNs.
#Exercise 3
#Create a set of points and a set of polygons

#Compute the distance matrix for both sets.

#Select one polygon of the distance matrix, and plot the closests and the farthest point to that polygon.
#Let me create some hulls (polygons):

systems.convex_hull.plot()
<Axes: >
/opt/python/envs/default/lib/python3.8/site-packages/geopandas/plotting.py:409: UserWarning: The GeoSeries you are attempting to plot is empty. Nothing has been displayed.
warnings.warn(
#Now, a GDF for the hulls:

systems_hulls=systems.convex_hull.to_frame()
systems_hulls['system']=['Amazon''Parana']
systems_hulls.rename(columns={0:'geometry'},inplace=True)
systems_hulls=systems_hulls.set_geometry('geometry')
systems_hulls.crs="EPSG:5641"
systems_hulls
#Next, the distance matrix:

distanceMatrixKM_sysHull_air=systems_hulls.set_index('system').geometry.apply\
(lambda g: largeAirports.set_index('name').geometry.distance(g)/1000).\
sort_index(axis=0).sort_index(axis=1)

distanceMatrixKM_sysHull_air
TypeError: (<class 'geopandas.geoseries.GeoSeries'>, <class 'NoneType'>)
#All the minimal differences:

mins=distanceMatrixKM_sysHull_air.idxmin(axis="columns")
mins
NameError: name 'distanceMatrixKM_sysHull_air' is not defined
# plotting
base=systems_hulls.explore()
largeAirports[largeAirports.name.isin(mins)].explore(m=base,color='red',marker_kwds=dict(radius=10))
largeAirports[~largeAirports.name.isin(mins)].explore(m=base,color='blue',marker_kwds=dict(radius=5))
ValueError: Location values cannot contain NaNs.
/opt/python/envs/default/lib/python3.8/site-packages/geopandas/array.py:968: RuntimeWarning: All-NaN slice encountered
np.nanmin(b[:, 0]), # minx
/opt/python/envs/default/lib/python3.8/site-packages/geopandas/array.py:969: RuntimeWarning: All-NaN slice encountered
np.nanmin(b[:, 1]), # miny
/opt/python/envs/default/lib/python3.8/site-packages/geopandas/array.py:970: RuntimeWarning: All-NaN slice encountered
np.nanmax(b[:, 2]), # maxx
/opt/python/envs/default/lib/python3.8/site-packages/geopandas/array.py:971: RuntimeWarning: All-NaN slice encountered
np.nanmax(b[:, 3]), # maxy
#Exercise 4
#Create a set of points and a set of lines

#Get the buffer for the lines, select different values for the distance.

#Keep the points that are within the buffer (as in point 2, you need to play with differn distances until you show something interesting.
#Using Buffers
#A very important case in distance analysis is the use of buffers:

# remember:
distanceMatrixKM_riv_air
# getting a value (it can be any value)
distanceMatrixKM_riv_air.loc['Colorado'].min()
192.39775507831118
#We can use any value to create a buffer:

minMts=distanceMatrixKM_riv_air.loc['Colorado'].min()*1000

#the buffer is a polygon:
rivers[rivers.NAME=='Colorado'].buffer(distance = minMts)
# see buffer:
bufferAroundColorado=rivers[rivers.NAME=='Colorado'].buffer(distance = minMts)
bufferAsBase=bufferAroundColorado.explore(color='red')
rivers[rivers.NAME=='Colorado'].explore(m=bufferAsBase,color='blue',style_kwds={'weight':0.5})
#Above we used the buffer (red polygon), and the river (blue). Let me add a layer of airports (small ones):

small_airports=airports[airports.kind=='small_airport']

# plotting
rivers[rivers.NAME=='Colorado'].explore(m=bufferAsBase,color='blue',style_kwds={'weight':0.5})
small_airports.explore(m=bufferAsBase,color='black')
#Now, we can use the buffer (polygon) to keep the airports thar are at that particular distance around the river:

riversWithinBuffer=small_airports.clip(mask=bufferAroundColorado)
#
riversWithinBuffer
bufferAsBase=bufferAroundColorado.explore(color='red')
rivers[rivers.NAME=='Colorado'].explore(m=bufferAsBase,color='blue',style_kwds={'weight':0.5})
riversWithinBuffer.explore(m=bufferAsBase,color='black')
# minimum of all the minimum by row
distanceMatrixKM_riv_air.min(axis=1).min() 
192.39775507831118
# using the previous value
minMinMts_5=5*distanceMatrixKM_riv_air.min(axis=1).min()*1000


allMinBuffer=rivers.buffer(distance = minMinMts_5).explore(color='red')
rivers.explore(m=allMinBuffer,color='blue',style_kwds={'weight':0.5})
small_airports.explore(m=allMinBuffer,color='black')
# you see all the buffer polygons:
rivers.buffer(distance = minMinMts_5)
# notice
riversAll_buf=rivers.buffer(distance = minMinMts_5)
type(riversAll_buf)
geopandas.geoseries.GeoSeries
# formatting
riversAll_bufDF=riversAll_buf.to_frame()
riversAll_bufDF.rename(columns={0:'geometry'},inplace=True)
riversAll_bufDF = riversAll_bufDF.set_geometry("geometry")
riversAll_bufDF.crs
<Projected CRS: EPSG:6366>
Name: Mexico ITRF2008 / UTM zone 11N
Axis Info [cartesian]:
- E[east]: Easting (metre)
- N[north]: Northing (metre)
Area of Use:
- name: Mexico west of 114°W, onshore and offshore.
- bounds: (-122.19, 15.01, -114.0, 32.72)
Coordinate Operation:
- name: UTM zone 11N
- method: Transverse Mercator
Datum: Mexico ITRF2008
- Ellipsoid: GRS 1980
- Prime Meridian: Greenwich
allRiversWithinBuffs=small_airports.clip(riversAll_bufDF)
allRiversWithinBuffs
# simple
base=riversAll_bufDF.plot(color='yellow')
allRiversWithinBuffs.plot(ax=base, color='green'markersize=1)
<Axes: >
# folium

base=riversAll_bufDF.explore(color='yellow')
allRiversWithinBuffs.explore(m=base, color='green')
Created using Figma